/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.rpc.saas;

import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.util.JEUUID;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import org.apache.servicecomb.provider.pojo.RpcSchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RpcSchema(schemaId = "metaTenantInstallRpcService")
public class MetaTenantInstallRpcServiceImpl implements MetaTenantInstallRpcService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;

    @Override
    @Transactional
    public Map<String, String> installMetaResource(DynaBean tenantBean, DynaBean product, Map<String, List<DynaBean>> resourceMap) {
        List<DynaBean> dictionaryBeanList = resourceMap.get("dictionary");
        List<DynaBean> variableBeanList = resourceMap.get("variable");
        List<DynaBean> funcBeanList = resourceMap.get("func");
        installDictionaryList(tenantBean, product, dictionaryBeanList);
        installVariableList(tenantBean, product, variableBeanList);
        return installFuncList(tenantBean, product, funcBeanList);
    }

    @Override
    public void uninstallMetaResource(DynaBean tenantBean, DynaBean product, Map<String, List<DynaBean>> resourceMap) {
        List<DynaBean> dictionaryBeanList = resourceMap.get("dictionary");
        List<DynaBean> variableBeanList = resourceMap.get("variable");
        List<DynaBean> funcBeanList = resourceMap.get("func");
        uninstallDictionaryList(tenantBean, product, dictionaryBeanList);
        uninstallVariableList(tenantBean, product, variableBeanList);
        uninstallFuncList(tenantBean, product, funcBeanList);
    }

    private void installDictionaryList(DynaBean tenantBean, DynaBean product, List<DynaBean> configDictionaryBeanList) {
        if (configDictionaryBeanList == null || configDictionaryBeanList.isEmpty()) {
            return;
        }
        List<String> configIdList = new ArrayList<>();
        for (DynaBean eachConfigBean : configDictionaryBeanList) {
            configIdList.add(eachConfigBean.getStr("PROZY_ZY_ID"));
        }

        List<DynaBean> dictionaryItemBeanList = metaService.select("JE_CORE_DICTIONARYITEM", ConditionsWrapper.builder()
                .in("DICTIONARYITEM_DICTIONARY_ID", configIdList));
        //设置原始的字典项为系统租户字典项
        metaService.executeSql("UPDATE JE_CORE_DICTIONARYITEM SET SY_TENANT_ID={0},SY_TENANT_NAME={1} WHERE DICTIONARYITEM_DICTIONARY_ID IN ({2})", "system", "系统租户", configIdList);
        for (DynaBean eachDicionaryItemBean : dictionaryItemBeanList) {
            eachDicionaryItemBean.set("DICTIONARYITEM_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
            eachDicionaryItemBean.set("JE_CORE_DICTIONARYITEM_ID", JEUUID.uuid());
            eachDicionaryItemBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
            eachDicionaryItemBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
            commonService.buildModelCreateInfo(eachDicionaryItemBean);
            metaService.insert(eachDicionaryItemBean);
        }

    }

    private void uninstallDictionaryList(DynaBean tenantBean, DynaBean product, List<DynaBean> configDictionaryBeanList) {
        if (configDictionaryBeanList == null || configDictionaryBeanList.isEmpty()) {
            return;
        }
        List<String> configIdList = new ArrayList<>();
        for (DynaBean eachConfigBean : configDictionaryBeanList) {
            configIdList.add(eachConfigBean.getStr("PROZY_ZY_ID"));
        }
        metaService.delete("JE_CORE_DICTIONARYITEM", ConditionsWrapper.builder()
                .eq("DICTIONARYITEM_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"))
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID")));
    }

    private void installVariableList(DynaBean tenantBean, DynaBean product, List<DynaBean> configVariableBeanList) {
        if (configVariableBeanList == null || configVariableBeanList.isEmpty()) {
            return;
        }
        List<String> configIdList = new ArrayList<>();
        for (DynaBean eachConfigBean : configVariableBeanList) {
            configIdList.add(eachConfigBean.getStr("PROZY_ZY_ID"));
        }

        //设置原始的字典项为系统租户字典项
        metaService.executeSql("UPDATE JE_CORE_CONFIG SET SY_TENANT_ID={0},SY_TENANT_NAME={1} WHERE DICTIONARYITEM_DICTIONARY_ID IN ({2})",
                "system", "系统租户", configIdList);
        List<DynaBean> variableBeanList = metaService.select("JE_CORE_CONFIG", ConditionsWrapper.builder()
                .in("JE_CORE_CONFIG_ID", configIdList));
        for (DynaBean eachVariableBean : variableBeanList) {
            eachVariableBean.set("JE_CORE_CONFIG_ID", JEUUID.uuid());
            eachVariableBean.set("CONFIG_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
            eachVariableBean.set("CONFIG_CODE", eachVariableBean.getStr("CONFIG_CODE"));
            eachVariableBean.set("CONFIG_NAME", eachVariableBean.getStr("CONFIG_NAME"));
            eachVariableBean.set("CONFIG_REMARK", eachVariableBean.getStr("CONFIG_REMARK"));
            eachVariableBean.set("CONFIG_TYPE_CODE", eachVariableBean.getStr("CONFIG_TYPE_CODE"));
            eachVariableBean.set("CONFIG_ENABLED", eachVariableBean.getStr("CONFIG_ENABLED"));
            eachVariableBean.set("CONFIG_VALUE", eachVariableBean.getStr("CONFIG_VALUE"));
            eachVariableBean.set("CONFIG_TYPE_NAME", eachVariableBean.getStr("CONFIG_TYPE_NAME"));
            eachVariableBean.set("SY_PRODUCT_ID", eachVariableBean.getStr("SY_PRODUCT_ID"));
            eachVariableBean.set("SY_PRODUCT_NAME", eachVariableBean.getStr("SY_PRODUCT_NAME"));
            eachVariableBean.set("SY_PRODUCT_CODE", eachVariableBean.getStr("SY_PRODUCT_CODE"));
            eachVariableBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
            eachVariableBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
            commonService.buildModelCreateInfo(eachVariableBean);
            metaService.insert(eachVariableBean);
        }
    }

    private void uninstallVariableList(DynaBean tenantBean, DynaBean product, List<DynaBean> configVariableBeanList) {
        if (configVariableBeanList == null || configVariableBeanList.isEmpty()) {
            return;
        }
        List<String> configIdList = new ArrayList<>();
        for (DynaBean eachConfigBean : configVariableBeanList) {
            configIdList.add(eachConfigBean.getStr("PROZY_ZY_ID"));
        }
        metaService.delete("JE_CORE_CONFIG", ConditionsWrapper.builder()
                .eq("CONFIG_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"))
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID")));
    }

    private Map<String, String> installFuncList(DynaBean tenantBean, DynaBean product, List<DynaBean> configFuncBeanList) {
        if (configFuncBeanList == null || configFuncBeanList.isEmpty()) {
            return null;
        }
        List<String> configIdList = new ArrayList<>();
        for (DynaBean eachConfigBean : configFuncBeanList) {
            configIdList.add(eachConfigBean.getStr("PROZY_ZY_ID"));
        }

        //功能
        List<DynaBean> funcBeanList = metaService.select("JE_CORE_FUNCINFO", ConditionsWrapper.builder()
                .in("JE_CORE_FUNCINFO_ID", configIdList));
        if (funcBeanList == null || funcBeanList.isEmpty()) {
            return null;
        }

        List<JSONTreeNode> rootNodeList = findFuncRootNodes(funcBeanList);
        //新旧功能主键映射关系
        Map<String, String> oldNewFuncAssociationMap = new HashMap<>();

        Map<String, DynaBean> insertFuncBeanMap = new HashMap<>();
        for (JSONTreeNode eachRootNode : rootNodeList) {
            fillInsertBeanList(eachRootNode, tenantBean, insertFuncBeanMap, oldNewFuncAssociationMap, true);
        }

        //功能列表字段
        List<DynaBean> funcGridFieldList = metaService.select("JE_CORE_RESOURCECOLUMN", ConditionsWrapper.builder()
                .in("RESOURCECOLUMN_FUNCINFO_ID", configIdList));
        //功能表单字段
        List<DynaBean> funcFormFieldList = metaService.select("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder()
                .in("RESOURCEFIELD_FUNCINFO_ID", configIdList));
        //列表方案
        List<DynaBean> gridPlanList = metaService.select("JE_CORE_RESOURCECOLUMN_PLAN", ConditionsWrapper.builder()
                .in("PLAN_FUNCINFO_ID", configIdList));
        //列表打印方案
        List<DynaBean> gridPrintPlanList = metaService.select("JE_CORE_RESOURCECOLUMN_PRINT_PLAN", ConditionsWrapper.builder()
                .in("PLAN_FUNCINFO_ID", configIdList));
        //表单方案
        List<DynaBean> formPlanList = metaService.select("JE_CORE_RESOURCEFIELD_PLAN", ConditionsWrapper.builder()
                .in("PLAN_FUNCINFO_ID", configIdList));
        //表单打印方案
        //表单方案
        List<DynaBean> formPrintPlanList = metaService.select("JE_CORE_RESOURCEFIELD_PRINT_PLAN", ConditionsWrapper.builder()
                .in("PLAN_FUNCINFO_ID", configIdList));
        //高级查询配置
        List<DynaBean> superQueryBeanList = metaService.select("JE_CORE_GROUPQUERY", ConditionsWrapper.builder()
                .in("GROUPQUERY_GNID", configIdList));
        //功能业务配置
        List<DynaBean> funcBusinessBeanList = metaService.select("JE_CORE_FUNC_CONFIG", ConditionsWrapper.builder()
                .in("JE_CORE_FUNCINFO_ID", configIdList));
        //数据流转策略
        List<DynaBean> dataFlowBeanList = metaService.select("JE_CORE_DATAFLOW", ConditionsWrapper.builder()
                .in("DATAFLOW_FUNCINFO_ID", configIdList));
        //功能依赖
        List<DynaBean> funcRelyonBeanList = metaService.select("JE_CORE_FUNCRELYON", ConditionsWrapper.builder()
                .in("FUNCRELYON_FUNCINFO_ID", configIdList));
        //功能按钮
        List<DynaBean> funcButtonBeanList = metaService.select("JE_CORE_RESOURCEBUTTON", ConditionsWrapper.builder()
                .in("RESOURCEBUTTON_FUNCINFO_ID", configIdList));
        //查询策略
        List<DynaBean> queryStrategyBeanList = metaService.select("JE_CORE_QUERYSTRATEGY", ConditionsWrapper.builder()
                .in("QUERYSTRATEGY_FUNCINFO_ID", configIdList));
        //数据权限
        List<DynaBean> dataPermBeanList = metaService.select("JE_CORE_FUNCPERM", ConditionsWrapper.builder()
                .in("FUNCPERM_FUNCINFO_ID", configIdList));
        List<String> dataPermConfigIdList = new ArrayList<>();
        if (dataPermBeanList != null) {
            for (DynaBean eachDataPermBean : dataPermBeanList) {
                dataPermConfigIdList.add(eachDataPermBean.getStr("JE_CORE_FUNCPERM_ID"));
            }
        }
        //数据权限配置
        List<DynaBean> dataPermConfigBeanList = metaService.select("JE_CORE_FUNCPERM_CONFIG", ConditionsWrapper.builder()
                .in("CONFIG_FUNCPERM_ID", dataPermConfigIdList));

        DynaBean eachFuncBean;
        //写入新功能
        String originFuncId;
        String newFuncId;
        String originDataPermId;
        for (Map.Entry<String, DynaBean> eachEntry : insertFuncBeanMap.entrySet()) {
            eachFuncBean = eachEntry.getValue();
            originFuncId = eachEntry.getKey();
            newFuncId = eachFuncBean.getStr("JE_CORE_FUNCINFO_ID");
            eachFuncBean.set("FUNCINFO_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
            //写入功能
            metaService.insert(eachEntry.getValue());
            for (DynaBean eachGridFieldBean : funcGridFieldList) {
                if (!eachGridFieldBean.getStr("RESOURCECOLUMN_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachGridFieldBean.set("JE_CORE_RESOURCECOLUMN_ID", JEUUID.uuid());
                eachGridFieldBean.set("RESOURCECOLUMN_FUNCINFO_ID", newFuncId);
                eachGridFieldBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachGridFieldBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachGridFieldBean.set("RESOURCECOLUMN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachGridFieldBean);
                metaService.insert(eachGridFieldBean);
            }
            for (DynaBean eachFormFieldBean : funcFormFieldList) {
                if (!eachFormFieldBean.getStr("RESOURCEFIELD_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachFormFieldBean.set("JE_CORE_RESOURCEFIELD_ID", JEUUID.uuid());
                eachFormFieldBean.set("RESOURCEFIELD_FUNCINFO_ID", newFuncId);
                eachFormFieldBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachFormFieldBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachFormFieldBean.set("RESOURCEFIELD_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachFormFieldBean);
                metaService.insert(eachFormFieldBean);
            }
            for (DynaBean eachGridPlanBean : gridPlanList) {
                if (!eachGridPlanBean.getStr("PLAN_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachGridPlanBean.set("JE_CORE_RESOURCECOLUMN_PLAN_ID", JEUUID.uuid());
                eachGridPlanBean.set("PLAN_FUNCINFO_ID", newFuncId);
                eachGridPlanBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachGridPlanBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachGridPlanBean.set("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachGridPlanBean);
                metaService.insert(eachGridPlanBean);
            }
            for (DynaBean eachGridPrintPlanBean : gridPrintPlanList) {
                if (!eachGridPrintPlanBean.getStr("PLAN_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachGridPrintPlanBean.set("JE_CORE_RESOURCECOLUMN_PRINT_PLAN_ID", JEUUID.uuid());
                eachGridPrintPlanBean.set("PLAN_FUNCINFO_ID", newFuncId);
                eachGridPrintPlanBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachGridPrintPlanBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachGridPrintPlanBean.set("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachGridPrintPlanBean);
                metaService.insert(eachGridPrintPlanBean);
            }
            for (DynaBean eachFormPlanBean : formPlanList) {
                if (!eachFormPlanBean.getStr("PLAN_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachFormPlanBean.set("JE_CORE_RESOURCEFIELD_PLAN_ID", JEUUID.uuid());
                eachFormPlanBean.set("PLAN_FUNCINFO_ID", newFuncId);
                eachFormPlanBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachFormPlanBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachFormPlanBean.set("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachFormPlanBean);
                metaService.insert(eachFormPlanBean);
            }
            for (DynaBean eachFormPrintPlanBean : formPrintPlanList) {
                if (!eachFormPrintPlanBean.getStr("PLAN_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachFormPrintPlanBean.set("JE_CORE_RESOURCECOLUMN_PRINT_PLAN_ID", JEUUID.uuid());
                eachFormPrintPlanBean.set("PLAN_FUNCINFO_ID", newFuncId);
                eachFormPrintPlanBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachFormPrintPlanBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachFormPrintPlanBean.set("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachFormPrintPlanBean);
                metaService.insert(eachFormPrintPlanBean);
            }
            for (DynaBean eachSuperQueryBean : superQueryBeanList) {
                if (!eachSuperQueryBean.getStr("GROUPQUERY_GNID").equals(originFuncId)) {
                    continue;
                }
                eachSuperQueryBean.set("JE_CORE_GROUPQUERY_ID", JEUUID.uuid());
                eachSuperQueryBean.set("GROUPQUERY_GNID", newFuncId);
                eachSuperQueryBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachSuperQueryBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachSuperQueryBean.set("GROUPQUERY_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachSuperQueryBean);
                metaService.insert(eachSuperQueryBean);
            }
            for (DynaBean eachFuncBusinessBean : funcBusinessBeanList) {
                if (!eachFuncBusinessBean.getStr("JE_CORE_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachFuncBusinessBean.set("JE_CORE_FUNC_CONFIG_ID", JEUUID.uuid());
                eachFuncBusinessBean.set("JE_CORE_FUNCINFO_ID", newFuncId);
                eachFuncBusinessBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachFuncBusinessBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachFuncBusinessBean.set("CONFIG_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachFuncBusinessBean);
                metaService.insert(eachFuncBusinessBean);
            }
            for (DynaBean eachDataFlowBean : dataFlowBeanList) {
                if (!eachDataFlowBean.getStr("DATAFLOW_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachDataFlowBean.set("JE_CORE_DATAFLOW_ID", JEUUID.uuid());
                eachDataFlowBean.set("DATAFLOW_FUNCINFO_ID", newFuncId);
                eachDataFlowBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachDataFlowBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachDataFlowBean.set("DATAFLOW_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachDataFlowBean);
                metaService.insert(eachDataFlowBean);
            }
            for (DynaBean eachFuncRelyonBean : funcRelyonBeanList) {
                if (!eachFuncRelyonBean.getStr("FUNCRELYON_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachFuncRelyonBean.set("JE_CORE_FUNCRELYON_ID", JEUUID.uuid());
                eachFuncRelyonBean.set("FUNCRELYON_FUNCINFO_ID", newFuncId);
                eachFuncRelyonBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachFuncRelyonBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachFuncRelyonBean.set("FUNCRELYON_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachFuncRelyonBean);
                metaService.insert(eachFuncRelyonBean);
            }
            for (DynaBean eachFuncButtonBean : funcButtonBeanList) {
                if (!eachFuncButtonBean.getStr("RESOURCEBUTTON_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachFuncButtonBean.set("JE_CORE_RESOURCEBUTTON_ID", JEUUID.uuid());
                eachFuncButtonBean.set("RESOURCEBUTTON_FUNCINFO_ID", newFuncId);
                eachFuncButtonBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachFuncButtonBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachFuncButtonBean.set("RESOURCEBUTTON_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachFuncButtonBean);
                metaService.insert(eachFuncButtonBean);
            }
            for (DynaBean eachQueryStrategyBean : queryStrategyBeanList) {
                if (!eachQueryStrategyBean.getStr("QUERYSTRATEGY_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                eachQueryStrategyBean.set("JE_CORE_QUERYSTRATEGY_ID", JEUUID.uuid());
                eachQueryStrategyBean.set("QUERYSTRATEGY_FUNCINFO_ID", newFuncId);
                eachQueryStrategyBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachQueryStrategyBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachQueryStrategyBean.set("QUERYSTRATEGY_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachQueryStrategyBean);
                metaService.insert(eachQueryStrategyBean);
            }
            for (DynaBean eachDataPermBean : dataPermBeanList) {
                if (!eachDataPermBean.getStr("FUNCPERM_FUNCINFO_ID").equals(originFuncId)) {
                    continue;
                }
                originDataPermId = eachDataPermBean.getStr("JE_CORE_FUNCPERM_ID");
                eachDataPermBean.set("JE_CORE_FUNCPERM_ID", JEUUID.uuid());
                eachDataPermBean.set("FUNCPERM_FUNCINFO_ID", newFuncId);
                eachDataPermBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachDataPermBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachDataPermBean.set("FUNCPERM_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachDataPermBean);
                metaService.insert(eachDataPermBean);
                for (DynaBean eachDataPermConfigBean : dataPermConfigBeanList) {
                    if (!eachDataPermConfigBean.getStr("CONFIG_FUNCPERM_ID").equals(originDataPermId)) {
                        continue;
                    }
                    eachDataPermConfigBean.set("JE_CORE_FUNCPERM_CONFIG_ID", JEUUID.uuid());
                    eachDataPermConfigBean.set("CONFIG_FUNCPERM_ID", eachDataPermBean.getStr("JE_CORE_FUNCPERM_ID"));
                    eachDataPermConfigBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                    eachDataPermConfigBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                    eachDataPermConfigBean.set("CONFIG_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                    commonService.buildModelCreateInfo(eachDataPermConfigBean);
                    metaService.insert(eachDataPermConfigBean);
                }
            }
        }

        //主子功能关系和主子功能关联字段
        //子功能
        List<DynaBean> subFuncBeanList = metaService.select("JE_CORE_FUNCRELATION", ConditionsWrapper.builder()
                .in("FUNCRELATION_FUNCINFO_ID", configIdList));
        List<DynaBean> mainSubAssosicationBeanList = metaService.select("JE_CORE_ASSOCIATIONFIELD", ConditionsWrapper.builder()
                .in("ASSOCIATIONFIELD_FID", configIdList).or().in("ASSOCIATIONFIELD_PID", configIdList));
        String eachOriginSubFuncRelationId;
        for (DynaBean eachSubFuncBean : subFuncBeanList) {
            eachOriginSubFuncRelationId = eachSubFuncBean.getStr("JE_CORE_FUNCRELATION_ID");
            eachSubFuncBean.set("JE_CORE_FUNCRELATION_ID", JEUUID.uuid());
            eachSubFuncBean.set("FUNCRELATION_FUNCINFO_ID", oldNewFuncAssociationMap.get(eachSubFuncBean.getStr("FUNCRELATION_FUNCINFO_ID")));
            eachSubFuncBean.set("FUNCRELATION_FUNCID", oldNewFuncAssociationMap.get(eachSubFuncBean.getStr("FUNCRELATION_FUNCID")));
            eachSubFuncBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
            eachSubFuncBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
            eachSubFuncBean.set("FUNCRELATION_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
            commonService.buildModelCreateInfo(eachSubFuncBean);
            metaService.insert(eachSubFuncBean);
            //主子功能关联字段
            for (DynaBean eachMainSubAssociationBean : mainSubAssosicationBeanList) {
                if (!eachMainSubAssociationBean.getStr("ASSOCIATIONFIELD_FUNCRELAT_ID").equals(eachOriginSubFuncRelationId)) {
                    continue;
                }
                eachMainSubAssociationBean.set("JE_CORE_ASSOCIATIONFIELD_ID", JEUUID.uuid());
                eachMainSubAssociationBean.set("ASSOCIATIONFIELD_FID", oldNewFuncAssociationMap.get(eachMainSubAssociationBean.getStr("ASSOCIATIONFIELD_FID")));
                eachMainSubAssociationBean.set("ASSOCIATIONFIELD_PID", oldNewFuncAssociationMap.get(eachMainSubAssociationBean.getStr("ASSOCIATIONFIELD_PID")));
                eachMainSubAssociationBean.set("ASSOCIATIONFIELD_FUNCRELAT_ID", eachSubFuncBean.getStr("JE_CORE_FUNCRELATION_ID"));
                eachMainSubAssociationBean.set("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
                eachMainSubAssociationBean.set("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
                eachMainSubAssociationBean.set("ASSOCIATIONFIELD_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID"));
                commonService.buildModelCreateInfo(eachMainSubAssociationBean);
                metaService.insert(eachMainSubAssociationBean);
            }
        }
        return oldNewFuncAssociationMap;
    }

    private void uninstallFuncList(DynaBean tenantBean, DynaBean product, List<DynaBean> configFuncBeanList) {
        if (configFuncBeanList == null || configFuncBeanList.isEmpty()) {
            return;
        }
        List<String> configIdList = new ArrayList<>();
        for (DynaBean eachConfigBean : configFuncBeanList) {
            configIdList.add(eachConfigBean.getStr("PROZY_ZY_ID"));
        }
        metaService.delete("JE_CORE_FUNCINFO", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("FUNCINFO_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_RESOURCECOLUMN", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("RESOURCECOLUMN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("RESOURCEFIELD_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_RESOURCECOLUMN_PLAN", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_RESOURCECOLUMN_PRINT_PLAN", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_RESOURCEFIELD_PLAN", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_RESOURCEFIELD_PRINT_PLAN", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("PLAN_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_GROUPQUERY", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("GROUPQUERY_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_FUNC_CONFIG", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("CONFIG_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_DATAFLOW", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("DATAFLOW_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_FUNCRELYON", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("FUNCRELYON_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_RESOURCEBUTTON", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("RESOURCEBUTTON_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_QUERYSTRATEGY", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("QUERYSTRATEGY_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_FUNCPERM", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("FUNCPERM_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_FUNCPERM_CONFIG", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("CONFIG_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_FUNCRELATION", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("FUNCRELATION_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
        metaService.delete("JE_CORE_ASSOCIATIONFIELD", ConditionsWrapper.builder()
                .eq("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"))
                .eq("ASSOCIATIONFIELD_SAAS_PID", product.getStr("JE_SAAS_PRODUCT_ID")));
    }

    private void fillInsertBeanList(JSONTreeNode rootNode, DynaBean tenantBean, Map<String, DynaBean> insertBeanMap, Map<String, String> oldNewFuncAssociationMap, boolean top) {
        String newId;
        String originId;
        String originWorkflowId;
        String newWorkflowId;
        if (top) {
            newId = JEUUID.uuid();
            newWorkflowId = JEUUID.uuid();
            originId = rootNode.getId();
            oldNewFuncAssociationMap.put(originId, newId);
            originWorkflowId = rootNode.getBean().get("FUNCINFO_BINDING_WORKFLOWID") == null ? null : (String) rootNode.getBean().get("FUNCINFO_BINDING_WORKFLOWID");
            if (!Strings.isNullOrEmpty(originWorkflowId)) {
                oldNewFuncAssociationMap.put(originWorkflowId, newWorkflowId);
                rootNode.getBean().put("FUNCINFO_BINDING_WORKFLOWID", newWorkflowId);
            }

            rootNode.setId(newId);
            rootNode.setParent("/ROOT");
            rootNode.setNodePath("/ROOT/" + newId);
            rootNode.getBean().put(BeanService.KEY_TABLE_CODE, "JE_CORE_FUNCINFO");
            rootNode.getBean().put("originId", originId);
            rootNode.getBean().put("JE_CORE_FUNCINFO_ID", newId);
            rootNode.getBean().put("SY_PATH", "/ROOT/" + newId);
            rootNode.getBean().put("SY_PARENT_PATH", "/ROOT");
            rootNode.getBean().put("FUNCINFO_FUNCNAME", rootNode.getBean().get("FUNCINFO_FUNCNAME") + "【" + tenantBean.getStr("TENANT_NAME") + "】");
            rootNode.getBean().put("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
            rootNode.getBean().put("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
            DynaBean rootBean = new DynaBean("JE_CORE_FUNCINFO", true);
            rootBean.setValues((Map<String, Object>) rootNode.getBean());
            insertBeanMap.put(originId, rootBean);
        }

        for (JSONTreeNode eachChildNode : rootNode.getChildren()) {
            newId = JEUUID.uuid();
            newWorkflowId = JEUUID.uuid();
            originId = eachChildNode.getId();
            oldNewFuncAssociationMap.put(originId, newId);
            originWorkflowId = eachChildNode.getBean().get("FUNCINFO_BINDING_WORKFLOWID") == null ? null : (String) eachChildNode.getBean().get("FUNCINFO_BINDING_WORKFLOWID");
            if (!Strings.isNullOrEmpty(originWorkflowId)) {
                oldNewFuncAssociationMap.put(originWorkflowId, newWorkflowId);
                eachChildNode.getBean().put("FUNCINFO_BINDING_WORKFLOWID", newWorkflowId);
            }
            eachChildNode.setId(newId);
            eachChildNode.setParent(rootNode.getId());
            eachChildNode.setNodePath(rootNode.getNodePath() + "/" + newId);
            eachChildNode.getBean().put(BeanService.KEY_TABLE_CODE, "JE_CORE_FUNCINFO");
            eachChildNode.getBean().put("originId", originId);
            eachChildNode.getBean().put("JE_CORE_FUNCINFO_ID", newId);
            eachChildNode.getBean().put("SY_PARENT", rootNode.getId());
            eachChildNode.getBean().put("SY_PATH", eachChildNode.getNodePath());
            eachChildNode.getBean().put("SY_PARENT_PATH", rootNode.getNodePath());
            eachChildNode.getBean().put("FUNCINFO_FUNCNAME", eachChildNode.getBean().get("FUNCINFO_FUNCNAME") + "【" + tenantBean.getStr("TENANT_NAME") + "】");
            eachChildNode.getBean().put("SY_TENANT_ID", tenantBean.getStr("JE_SAAS_TENANT_ID"));
            eachChildNode.getBean().put("SY_TENANT_NAME", tenantBean.getStr("TENANT_NAME"));
            DynaBean childBean = new DynaBean("JE_CORE_FUNCINFO", true);
            childBean.setValues((Map<String, Object>) eachChildNode.getBean());
            insertBeanMap.put(originId, childBean);
            fillInsertBeanList(eachChildNode, tenantBean, insertBeanMap, oldNewFuncAssociationMap, false);
        }

    }

    /**
     * 查找根节点，并递归出树形结构
     *
     * @param funcBeanList
     * @return
     */
    private List<JSONTreeNode> findFuncRootNodes(List<DynaBean> funcBeanList) {
        List<JSONTreeNode> rootFuncBeanList = new ArrayList<>();
        List<String> funcPkIdList = new ArrayList<>();
        for (DynaBean eachFuncBean : funcBeanList) {
            funcPkIdList.add(eachFuncBean.getStr("JE_CORE_FUNCINFO_ID"));
        }

        JSONTreeNode eachRootNode;
        for (DynaBean eachFuncBean : funcBeanList) {
            if (funcPkIdList.contains(eachFuncBean.getStr("SY_PARENT"))) {
                continue;
            }
            eachRootNode = new JSONTreeNode();
            eachRootNode.setId(eachFuncBean.getStr("JE_CORE_FUNCINFO_ID"));
            eachRootNode.setText(eachFuncBean.getStr("FUNCINFO_FUNCNAME"));
            eachRootNode.setNodePath(eachFuncBean.getStr("SY_PATH"));
            eachRootNode.setParent(eachFuncBean.getStr("SY_PARENT"));
            eachRootNode.setBean(eachFuncBean.getValues());
            eachRootNode.setNodeType(eachFuncBean.getStr("FUNCINFO_FUNCTYPE"));
            rootFuncBeanList.add(eachRootNode);
        }

        for (JSONTreeNode eachNode : rootFuncBeanList) {
            formatFuncJsonTreeNode(eachNode, funcBeanList);
        }

        return rootFuncBeanList;
    }

    private void formatFuncJsonTreeNode(JSONTreeNode parentBeanNode, List<DynaBean> funcBeanList) {
        JSONTreeNode eachChildNode;
        for (DynaBean eachFuncBean : funcBeanList) {
            if (parentBeanNode.getId().equals(eachFuncBean.getStr("JE_CORE_FUNCINFO_ID"))) {
                continue;
            }
            if (!parentBeanNode.getId().equals(eachFuncBean.getStr("SY_PARENT"))) {
                continue;
            }
            eachChildNode = new JSONTreeNode();
            eachChildNode.setId(eachFuncBean.getStr("JE_CORE_FUNCINFO_ID"));
            eachChildNode.setText(eachFuncBean.getStr("FUNCINFO_FUNCNAME"));
            eachChildNode.setNodePath(eachFuncBean.getStr("SY_PATH"));
            eachChildNode.setParent(eachFuncBean.getStr("SY_PARENT"));
            eachChildNode.setBean(eachFuncBean.getValues());
            eachChildNode.setNodeType(eachFuncBean.getStr("FUNCINFO_FUNCTYPE"));
            parentBeanNode.getChildren().add(eachChildNode);
            formatFuncJsonTreeNode(eachChildNode, funcBeanList);
        }
    }

}
